package com.genexususa.eo.google.connection;

import com.genexususa.eo.google.data.*;
import com.google.api.ads.adwords.axis.v201406.cm.*;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;

public class AdExtensionManager {


    private static final int PAGE_SIZE = 5000;
    private String _clientId;

    public void SetClientId(String clientId) {
        this._clientId = clientId;
    }

    public String GetClientId() {
        return _clientId;
    }

    public void Finalize() {

        SessionController sc = SessionController.getInstance();
        sc.RemoveSession(_clientId);
    }


    public String CreateAdExtensionLocation(String xml) {

        try {
            String result = "";

            // Get the instance of service's factory
            ServiceFactory sf = ServiceFactory.getInstance();


            //GA_ResultCreateAdExtensionLocation res = new GA_ResultCreateAdExtensionLocation();
            GA_Result res = new GA_Result();

            //try{

            Util util = new Util();

            Document doc = util.loadXMLFromString(xml);

            XPathFactory factory = XPathFactory.newInstance();
            XPath xpath = factory.newXPath();

            XPathExpression expr
                    = xpath.compile("//GA_AdExtensionLocation");

            Object adExtensionLocationNodes = expr.evaluate(doc, XPathConstants.NODESET);

            NodeList adExtensionLocations = (NodeList) adExtensionLocationNodes;

            ArrayList<GA_ResultItem> extensionLocations = new ArrayList<GA_ResultItem>();

            if (adExtensionLocations.getLength() > 0) {

                for (int i = 0; i < adExtensionLocations.getLength(); i++) { // For all GA_AdExtensionLocation Nodes

                    Node n = adExtensionLocations.item(i);

                    NodeList children = n.getChildNodes();

                    if (children.getLength() > 0) {

                        //GA_AdExtensionLocation gaExtensionLocation = new GA_AdExtensionLocation();
                        GA_ResultItem gaExtensionLocation = new GA_ResultItem();
                        LocationExtension locationExtension = new LocationExtension();

                        Address address = new Address();

                        CampaignAdExtension campaignAdExtension = new CampaignAdExtension();

                        for (int j = 0; j < children.getLength(); j++) {

                            if (children.item(j).getNodeName().equalsIgnoreCase("CampaignId")) {
                                gaExtensionLocation.CampaignId = Long.parseLong(children.item(j).getTextContent());
                                campaignAdExtension.setCampaignId(Long.parseLong(children.item(j).getTextContent()));
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("SubCampaignGxId")) {
                                gaExtensionLocation.SubCampaignGxId = Long.parseLong(children.item(j).getTextContent());

                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("ExtensionGxId")) {
                                gaExtensionLocation.AdExtensionGxId = Long.parseLong(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("Status")) {

                                if (children.item(j).getTextContent().equalsIgnoreCase("A")) {
                                    campaignAdExtension.setStatus(CampaignAdExtensionStatus.ENABLED);
                                } else if (children.item(j).getTextContent().equalsIgnoreCase("D")) {
                                    campaignAdExtension.setStatus(CampaignAdExtensionStatus.REMOVED);
                                }

                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("ApprovalSts")) {

                                if (children.item(j).getTextContent().equalsIgnoreCase("A")) {
                                    campaignAdExtension.setApprovalStatus(CampaignAdExtensionApprovalStatus.APPROVED);
                                } else if (children.item(j).getTextContent().equalsIgnoreCase("U")) {
                                    campaignAdExtension.setApprovalStatus(CampaignAdExtensionApprovalStatus.UNCHECKED);
                                } else if (children.item(j).getTextContent().equalsIgnoreCase("D")) {
                                    campaignAdExtension.setApprovalStatus(CampaignAdExtensionApprovalStatus.DISAPPROVED);
                                }

                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("StreetAddress")) {
                                address.setStreetAddress(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("StreetAddress2")) {

                                if (children.item(j).getTextContent() != null && !children.item(j).getTextContent().equalsIgnoreCase(""))
                                    address.setStreetAddress2(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("CityName")) {
                                address.setCityName(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("ProvidenceName")) {
                                address.setProvinceName(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("ProvidenceCode")) {
                                address.setProvinceCode(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("PostalCode")) {
                                address.setPostalCode(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("CountryCode")) {
                                address.setCountryCode(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("companyName")) {
                                locationExtension.setCompanyName(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("phoneNumber")) {
                                locationExtension.setPhoneNumber(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("IconMediaId")) {
                                locationExtension.setIconMediaId(Long.parseLong(children.item(j).getTextContent()));
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("ImageMediaId")) {
                                locationExtension.setImageMediaId(Long.parseLong(children.item(j).getTextContent()));
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("Source")) {

                                if (children.item(j).getTextContent().equalsIgnoreCase("AF")) {
                                    locationExtension.setSource(LocationExtensionSource.ADWORDS_FRONTEND);
                                } else if (children.item(j).getTextContent().equalsIgnoreCase("LS")) {
                                    locationExtension.setSource(LocationExtensionSource.LBC_SYNC);
                                }
                            }
                        }

                        // Create geo location selector.
                        GeoLocationSelector selector = new GeoLocationSelector();
                        selector.setAddresses(new Address[]{address});

                        // Get geo location.
                        GeoLocation[] geoLocationResult = sf.GetGeoLocationService(this.GetClientId()).get(selector);
                        GeoLocation geoLocation = geoLocationResult[0];

                        locationExtension.setAddress(geoLocation.getAddress());
                        locationExtension.setGeoPoint(geoLocation.getGeoPoint());
                        locationExtension.setEncodedLocation(geoLocation.getEncodedLocation());
                        campaignAdExtension.setAdExtension(locationExtension);
                        gaExtensionLocation.AdExtensionLocation = locationExtension;
                        extensionLocations.add(gaExtensionLocation);
                    }
                }

                ArrayList<GA_ResultItem> created = new ArrayList<GA_ResultItem>();

                ArrayList<CampaignAdExtensionOperation> ops = new ArrayList<CampaignAdExtensionOperation>();

                for (GA_ResultItem extensionLocation : extensionLocations) {


                    CampaignAdExtension campaignAdExtension = new CampaignAdExtension();
                    campaignAdExtension.setCampaignId(extensionLocation.CampaignId);
                    campaignAdExtension.setAdExtension(extensionLocation.AdExtensionLocation);


                    CampaignAdExtensionOperation operation = new CampaignAdExtensionOperation();
                    operation.setOperand(campaignAdExtension);
                    operation.setOperator(Operator.ADD);

                    ops.add(operation);

                }

                CampaignAdExtensionServiceInterface adService = sf.GetCampaignAdExtensionService(this.GetClientId());

                CampaignAdExtensionOperation[] opsArray = new CampaignAdExtensionOperation[]{};

                CampaignAdExtensionOperation[] operations = ops.toArray(opsArray);

                //try{

                CampaignAdExtensionReturnValue returnValue = adService.mutate(operations);

                Thread.sleep(1000);

                int j = 0;

                for (int i = 0; i < returnValue.getValue().length; i++) {

                    GA_ResultItem createdAdExtension = new GA_ResultItem();

                    createdAdExtension.AdExtensionGxId = extensionLocations.get(i).AdExtensionGxId;
                    createdAdExtension.CampaignId = extensionLocations.get(i).CampaignId;
                    createdAdExtension.SubCampaignGxId = extensionLocations.get(i).SubCampaignGxId;

                    if (returnValue.getValue(i).getAdExtension() == null) {


                        createdAdExtension.AdExtensionId = 0L;
                        createdAdExtension.HasError = true;


                        ErrorsStruct errors = new ErrorsStruct();

                        errors.Message = returnValue.getPartialFailureErrors(j).getErrorString();

                        errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();

                        com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();

                        err.ErrorString = returnValue.getPartialFailureErrors(j).getErrorString();
                        err.fieldPath = returnValue.getPartialFailureErrors(j).getFieldPath();
                        err.Trigger = returnValue.getPartialFailureErrors(j).getTrigger();
                        err.Type = returnValue.getPartialFailureErrors(j).getApiErrorType();

                        j++;

                        errors.Errors.add(err);

                        createdAdExtension.Errors = errors;

                        created.add(createdAdExtension);
                    } else {

                        createdAdExtension.AdExtensionId = returnValue.getValue(i).getAdExtension().getId();

                        created.add(createdAdExtension);
                    }

                }


                    /*}catch (Exception exc){

                        exc.printStackTrace();
                        System.out.println(exc.getMessage());

                    }*/


                try {

                    JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                    Marshaller marshallerObj = contextObj.createMarshaller();
                    marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                    StringWriter sw = new StringWriter();

                    res.Items = created;

                    marshallerObj.marshal(res, sw);
                    result = sw.getBuffer().toString();
                    System.out.println(result);
                    String s = "";

                } catch (Exception exc) {
                    exc.printStackTrace();
                    result = exc.getMessage();
                }

            }


            /*}catch (Exception exc){
                exc.printStackTrace();
                result = exc.getMessage();
            }*/
            return result;

        } catch (Exception exc) {

            GA_Result res = new GA_Result();

            ArrayList<GA_ResultItem> items = new ArrayList<GA_ResultItem>();

            GA_ResultItem error = new GA_ResultItem();

            ErrorsStruct errors = new ErrorsStruct();

            errors.Message = exc.getMessage();

            errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();

            com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();

            StringWriter st = new StringWriter();
            exc.printStackTrace(new PrintWriter(st));

            err.UnknownError = st.toString();

            errors.Errors.add(err);

            error.Errors = errors;

            error.HasError = true;

            items.add(error);

            String result = "";

            try {

                JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                Marshaller marshallerObj = contextObj.createMarshaller();
                marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                StringWriter sw = new StringWriter();

                res.Items = items;

                marshallerObj.marshal(res, sw);
                result = sw.getBuffer().toString();
                System.out.println(result);
                return result;

            } catch (Exception ex) {
                ex.printStackTrace();
                result = ex.getMessage();
                return result;
            }
        }
    }

    public String UpdateAdExtensionLocation(String xml) {

        try {

            String result = "";

            // Get the instance of service's factory
            ServiceFactory sf = ServiceFactory.getInstance();


            //GA_ResultCreateAdExtensionLocation res = new GA_ResultCreateAdExtensionLocation();

            GA_Result res = new GA_Result();

            //try{

            Util util = new Util();

            Document doc = util.loadXMLFromString(xml);

            XPathFactory factory = XPathFactory.newInstance();
            XPath xpath = factory.newXPath();

            XPathExpression expr
                    = xpath.compile("//GA_AdExtensionLocation");

            Object adExtensionLocationNodes = expr.evaluate(doc, XPathConstants.NODESET);

            NodeList adExtensionLocations = (NodeList) adExtensionLocationNodes;

            ArrayList<GA_ResultItem> extensionLocations = new ArrayList<GA_ResultItem>();

            if (adExtensionLocations.getLength() > 0) {

                for (int i = 0; i < adExtensionLocations.getLength(); i++) { // For all GA_AdExtensionLocation Nodes

                    Node n = adExtensionLocations.item(i);

                    NodeList children = n.getChildNodes();

                    if (children.getLength() > 0) {

                        //GA_AdExtensionLocation gaExtensionLocation = new GA_AdExtensionLocation();

                        GA_ResultItem gaExtensionLocation = new GA_ResultItem();
                        LocationExtension locationExtension = new LocationExtension();

                        Address address = new Address();

                        CampaignAdExtension campaignAdExtension = new CampaignAdExtension();

                        for (int j = 0; j < children.getLength(); j++) {

                            if (children.item(j).getNodeName().equalsIgnoreCase("CampaignId")) {
                                gaExtensionLocation.CampaignId = Long.parseLong(children.item(j).getTextContent());
                                campaignAdExtension.setCampaignId(Long.parseLong(children.item(j).getTextContent()));
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("SubCampaignGxId")) {
                                gaExtensionLocation.SubCampaignGxId = Long.parseLong(children.item(j).getTextContent());

                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("ExtensionGxId")) {
                                gaExtensionLocation.AdExtensionGxId = Long.parseLong(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("ExtensionId")) {
                                gaExtensionLocation.AdExtensionId = Long.parseLong(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("Status")) {

                                if (children.item(j).getTextContent().equalsIgnoreCase("A")) {
                                    campaignAdExtension.setStatus(CampaignAdExtensionStatus.ENABLED);
                                } else if (children.item(j).getTextContent().equalsIgnoreCase("D")) {
                                    campaignAdExtension.setStatus(CampaignAdExtensionStatus.REMOVED);
                                }

                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("ApprovalSts")) {

                                if (children.item(j).getTextContent().equalsIgnoreCase("A")) {
                                    campaignAdExtension.setApprovalStatus(CampaignAdExtensionApprovalStatus.APPROVED);
                                } else if (children.item(j).getTextContent().equalsIgnoreCase("U")) {
                                    campaignAdExtension.setApprovalStatus(CampaignAdExtensionApprovalStatus.UNCHECKED);
                                } else if (children.item(j).getTextContent().equalsIgnoreCase("D")) {
                                    campaignAdExtension.setApprovalStatus(CampaignAdExtensionApprovalStatus.DISAPPROVED);
                                }

                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("StreetAddress")) {
                                address.setStreetAddress(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("StreetAddress2")) {
                                address.setStreetAddress2(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("CityName")) {
                                address.setCityName(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("ProvidenceName")) {
                                address.setProvinceName(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("ProvidenceCode")) {
                                address.setProvinceCode(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("PostalCode")) {
                                address.setPostalCode(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("CountryCode")) {
                                address.setCountryCode(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("companyName")) {
                                locationExtension.setCompanyName(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("phoneNumber")) {
                                locationExtension.setPhoneNumber(children.item(j).getTextContent());
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("IconMediaId")) {
                                locationExtension.setIconMediaId(Long.parseLong(children.item(j).getTextContent()));
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("ImageMediaId")) {
                                locationExtension.setImageMediaId(Long.parseLong(children.item(j).getTextContent()));
                            }

                            if (children.item(j).getNodeName().equalsIgnoreCase("Source")) {

                                if (children.item(j).getTextContent().equalsIgnoreCase("AF")) {
                                    locationExtension.setSource(LocationExtensionSource.ADWORDS_FRONTEND);
                                } else if (children.item(j).getTextContent().equalsIgnoreCase("LS")) {
                                    locationExtension.setSource(LocationExtensionSource.LBC_SYNC);
                                }
                            }
                        }

                        // Create geo location selector.
                        GeoLocationSelector selector = new GeoLocationSelector();
                        selector.setAddresses(new Address[]{address});

                        // Get geo location.
                        GeoLocation[] geoLocationResult = sf.GetGeoLocationService(this.GetClientId()).get(selector);
                        GeoLocation geoLocation = geoLocationResult[0];

                        locationExtension.setId(gaExtensionLocation.AdExtensionId);
                        locationExtension.setAddress(geoLocation.getAddress());
                        locationExtension.setGeoPoint(geoLocation.getGeoPoint());
                        locationExtension.setEncodedLocation(geoLocation.getEncodedLocation());
                        campaignAdExtension.setAdExtension(locationExtension);
                        gaExtensionLocation.AdExtensionLocation = locationExtension;
                        extensionLocations.add(gaExtensionLocation);
                    }
                }

                ArrayList<GA_ResultItem> created = new ArrayList<GA_ResultItem>();

                ArrayList<CampaignAdExtensionOperation> ops = new ArrayList<CampaignAdExtensionOperation>();


                for (GA_ResultItem extensionLocation : extensionLocations) {


                    CampaignAdExtension campaignAdExtension = new CampaignAdExtension();
                    campaignAdExtension.setCampaignId(extensionLocation.CampaignId);
                    campaignAdExtension.setAdExtension(extensionLocation.AdExtensionLocation);


                    CampaignAdExtensionOperation operation = new CampaignAdExtensionOperation();
                    operation.setOperand(campaignAdExtension);
                    operation.setOperator(Operator.SET);

                    ops.add(operation);
                }


                CampaignAdExtensionServiceInterface adService = sf.GetCampaignAdExtensionService(this.GetClientId());

                CampaignAdExtensionOperation[] opsArray = new CampaignAdExtensionOperation[]{};

                CampaignAdExtensionOperation[] operations = ops.toArray(opsArray);

                //try{

                CampaignAdExtensionReturnValue returnValue = adService.mutate(operations);

                Thread.sleep(1000);

                int j = 0;

                for (int i = 0; i < returnValue.getValue().length; i++) {

                    GA_ResultItem createdAdExtension = new GA_ResultItem();

                    createdAdExtension.AdExtensionGxId = extensionLocations.get(i).AdExtensionGxId;
                    createdAdExtension.CampaignId = extensionLocations.get(i).CampaignId;
                    createdAdExtension.SubCampaignGxId = extensionLocations.get(i).SubCampaignGxId;

                    if (returnValue.getValue(i).getAdExtension() == null) {


                        createdAdExtension.AdExtensionId = 0L;
                        createdAdExtension.HasError = true;


                        ErrorsStruct errors = new ErrorsStruct();

                        errors.Message = returnValue.getPartialFailureErrors(j).getErrorString();

                        errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();

                        com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();

                        err.ErrorString = returnValue.getPartialFailureErrors(j).getErrorString();
                        err.fieldPath = returnValue.getPartialFailureErrors(j).getFieldPath();
                        err.Trigger = returnValue.getPartialFailureErrors(j).getTrigger();
                        err.Type = returnValue.getPartialFailureErrors(j).getApiErrorType();

                        j++;

                        errors.Errors.add(err);

                        createdAdExtension.Errors = errors;

                        created.add(createdAdExtension);
                    } else {

                        createdAdExtension.AdExtensionId = returnValue.getValue(i).getAdExtension().getId();

                        created.add(createdAdExtension);
                    }

                }

                try {

                    JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                    Marshaller marshallerObj = contextObj.createMarshaller();
                    marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                    StringWriter sw = new StringWriter();

                    res.Items = created;

                    marshallerObj.marshal(res, sw);
                    result = sw.getBuffer().toString();
                    System.out.println(result);
                    String s = "";

                } catch (Exception exc) {
                    exc.printStackTrace();
                    result = exc.getMessage();
                }

            }



            return result;

        } catch (Exception exc) {

            GA_Result res = new GA_Result();

            ArrayList<GA_ResultItem> items = new ArrayList<GA_ResultItem>();

            GA_ResultItem error = new GA_ResultItem();

            ErrorsStruct errors = new ErrorsStruct();

            errors.Message = exc.getMessage();

            errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();

            com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();

            StringWriter st = new StringWriter();
            exc.printStackTrace(new PrintWriter(st));

            err.UnknownError = st.toString();

            errors.Errors.add(err);

            error.Errors = errors;

            error.HasError = true;

            items.add(error);

            String result = "";

            try {

                JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                Marshaller marshallerObj = contextObj.createMarshaller();
                marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                StringWriter sw = new StringWriter();

                res.Items = items;

                marshallerObj.marshal(res, sw);
                result = sw.getBuffer().toString();
                System.out.println(result);
                return result;

            } catch (Exception ex) {
                ex.printStackTrace();
                result = ex.getMessage();
                return result;
            }
        }
    }

    public String DeleteAdExtensionLocation(Long campaignId, Long adExtensionId) {

        try {

            String result = "";

            // Get the instance of service's factory
            ServiceFactory sf = ServiceFactory.getInstance();

            CampaignAdExtensionServiceInterface adService = sf.GetCampaignAdExtensionService(this.GetClientId());

            //GA_ResultCreateAdExtensionLocation res = new GA_ResultCreateAdExtensionLocation();
            GA_Result res = new GA_Result();

            GA_ResultItem deleted = new GA_ResultItem();

            CampaignAdExtension campaignAdExtension = new CampaignAdExtension();
            campaignAdExtension.setCampaignId(campaignId);

            AdExtension adExtension = new AdExtension();
            adExtension.setId(adExtensionId);

            campaignAdExtension.setAdExtension(adExtension);

            CampaignAdExtensionOperation operation = new CampaignAdExtensionOperation();
            operation.setOperand(campaignAdExtension);
            operation.setOperator(Operator.REMOVE);

            CampaignAdExtensionOperation[] operations = new CampaignAdExtensionOperation[]{operation};

            deleted.CampaignId = campaignId;
            deleted.AdExtensionId = adExtensionId;

            //try{

            try {
                CampaignAdExtensionReturnValue returnValue = adService.mutate(operations);

                Thread.sleep(1000);

                //deleted.AdExtensionId = returnValue.getValue(0).getAdExtension().getId();

                deleted.HasError = false;
                res.Items.add(deleted);

            } catch (ApiException apiException) {


                boolean retry = false;

                ApiError[] apiErrors = apiException.getErrors();

                for (ApiError error : apiErrors) {

                    if (error.getErrorString().equalsIgnoreCase("RateExceededError.RATE_EXCEEDED")) {

                        Thread.sleep(35000);


                        operation = new CampaignAdExtensionOperation();
                        operation.setOperand(campaignAdExtension);
                        operation.setOperator(Operator.ADD);

                        operations = new CampaignAdExtensionOperation[]{operation};

                        CampaignAdExtensionReturnValue returnValue = adService.mutate(operations);

                        Thread.sleep(1000);

                        deleted.AdExtensionId = returnValue.getValue(0).getAdExtension().getId();

                        res.Items.add(deleted);

                        retry = true;

                    }
                }


                if (!retry) {


                    deleted.AdExtensionId = 0L;
                    //deleted.AdExtensionGxId = extensionLocation.AdExtensionGxId;
                    deleted.HasError = true;

                    for (ApiError apiError : apiErrors) {

                        ErrorsStruct errors = new ErrorsStruct();

                        errors.Message = apiError.getErrorString();

                        errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();

                        com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();

                        err.ErrorString = apiError.getErrorString();
                        err.fieldPath = apiError.getFieldPath();
                        err.Reason = apiException.getFaultReason();
                        err.Trigger = apiError.getTrigger();
                        err.Type = apiError.getApiErrorType();

                        errors.Errors.add(err);

                        deleted.Errors = errors;

                        res.Items.add(deleted);
                    }
                }
            }/*catch (Exception exc){
                exc.printStackTrace();
            }  */
        /*}catch (Exception exc){
            exc.printStackTrace();
        } */

            try {

                JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                Marshaller marshallerObj = contextObj.createMarshaller();
                marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                StringWriter sw = new StringWriter();

                marshallerObj.marshal(res, sw);
                result = sw.getBuffer().toString();
                System.out.println(result);

            } catch (Exception exc) {
                exc.printStackTrace();
                result = exc.getMessage();
            }

            return result;
        } catch (Exception exc) {

            GA_Result res = new GA_Result();

            ArrayList<GA_ResultItem> items = new ArrayList<GA_ResultItem>();

            GA_ResultItem error = new GA_ResultItem();

            ErrorsStruct errors = new ErrorsStruct();

            errors.Message = exc.getMessage();

            errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();

            com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();

            StringWriter st = new StringWriter();
            exc.printStackTrace(new PrintWriter(st));

            err.UnknownError = st.toString();

            errors.Errors.add(err);

            error.Errors = errors;

            error.HasError = true;

            items.add(error);

            String result = "";

            try {

                JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                Marshaller marshallerObj = contextObj.createMarshaller();
                marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                StringWriter sw = new StringWriter();

                res.Items = items;

                marshallerObj.marshal(res, sw);
                result = sw.getBuffer().toString();
                System.out.println(result);
                return result;

            } catch (Exception ex) {
                ex.printStackTrace();
                result = ex.getMessage();
                return result;
            }
        }
    }


    protected ArrayList<AdExtensionLocationReport> GetAdExtensionLocationReport(String clientId) {

        ArrayList<AdExtensionLocationReport> result = new ArrayList<AdExtensionLocationReport>();

        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();

        try {
            CampaignAdExtensionServiceInterface adService = sf.GetCampaignAdExtensionService(clientId);

            int offset = 0;

            // Create selector.
            Selector selector = new Selector();
            selector.setFields(new String[]{
                    "AdExtensionId",
                    "Address",
                    "ApprovalStatus",
                    "CompanyName",
                    "LocationExtensionSource",
                    "PhoneNumber",
                    "Status"
            });
            selector.setOrdering(new OrderBy[]{new OrderBy("AdExtensionId", SortOrder.ASCENDING)});
            selector.setPaging(new Paging(offset, PAGE_SIZE));

            Predicate predicate = new Predicate("Status", PredicateOperator.NOT_EQUALS, new String[]{"REMOVED"});
            Predicate[] predicates = new Predicate[]{predicate};
            selector.setPredicates(predicates);

            CampaignAdExtensionPage page = null;
            do {

                page = adService.get(selector);

                if (page.getEntries() != null && page.getEntries().length > 0) {
                    // Display results.
                    for (CampaignAdExtension campaignAdExtension : page.getEntries()) {

                        if (campaignAdExtension.getAdExtension().getAdExtensionType().equalsIgnoreCase("LocationExtension")) {
                            if (campaignAdExtension.getAdExtension() instanceof LocationExtension) {
                                LocationExtension locationExtension = (LocationExtension)campaignAdExtension.getAdExtension();
                                AdExtensionLocationReport adExtension = new AdExtensionLocationReport();

                                adExtension.AdExtensionId = locationExtension.getId();
                                adExtension.AddressLine1 = locationExtension.getAddress().getStreetAddress();
                                adExtension.AddressLine2 = locationExtension.getAddress().getStreetAddress2();
                                adExtension.CampaignId = campaignAdExtension.getCampaignId();
                                adExtension.CityName = locationExtension.getAddress().getCityName();
                                adExtension.CompanyName = locationExtension.getCompanyName();
                                adExtension.CountryCode = locationExtension.getAddress().getCountryCode();
                                adExtension.PhoneNumber = locationExtension.getPhoneNumber();
                                adExtension.PostalCode = locationExtension.getAddress().getPostalCode();
                                adExtension.ProvinceCode = locationExtension.getAddress().getProvinceCode();
                                adExtension.ProvinceName = locationExtension.getAddress().getProvinceName();

                                if (campaignAdExtension.getApprovalStatus() == CampaignAdExtensionApprovalStatus.APPROVED) {
                                    adExtension.ApprovalStatus = "A";
                                } else if (campaignAdExtension.getApprovalStatus() == CampaignAdExtensionApprovalStatus.DISAPPROVED) {
                                    adExtension.ApprovalStatus = "D";
                                } else if (campaignAdExtension.getApprovalStatus() == CampaignAdExtensionApprovalStatus.UNCHECKED) {
                                    adExtension.ApprovalStatus = "U";
                                }

                                if (locationExtension.getSource() == LocationExtensionSource.ADWORDS_FRONTEND) {
                                    adExtension.LocationExtensionSource = "AF";
                                } else if (locationExtension.getSource() == LocationExtensionSource.LBC_SYNC) {
                                    adExtension.LocationExtensionSource = "LS";
                                }

                                if (campaignAdExtension.getStatus() == CampaignAdExtensionStatus.ENABLED) {
                                    adExtension.Status = "A";
                                } else if (campaignAdExtension.getStatus() == CampaignAdExtensionStatus.REMOVED) {
                                    adExtension.Status = "D";
                                }

                                result.add(adExtension);
                            }
                        }

                    }
                }


                offset += PAGE_SIZE;
                selector.getPaging().setStartIndex(offset);

            } while (offset < page.getTotalNumEntries());


        } catch (Exception exc) {
            exc.printStackTrace(System.out);
        }

        return result;
    }

    protected ArrayList<SitelinksReport> GetFeedItemsSitelinksReport(String clientId){

        ArrayList<SitelinksReport> result = new ArrayList<SitelinksReport>();

        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();
        try {
            FeedItemServiceInterface feedItemService = sf.GetFeedItemServiceInterface(clientId);

            //ArrayList<Long> feedIds = GetFeedIds(clientId, "1");

            //HashMap<Long, ArrayList<Long>> feedsByCampaign = GetFeedsByCampaign(clientId);

            ArrayList<CampaignFeedMapping> feedsByCampaign = GetFeedsByCampaign(clientId, "1");

            SitelinksReport sitelink = new SitelinksReport();
            sitelink.Sitelinks = feedsByCampaign;


            result.add(sitelink);

       /* for(Long feedId : feedIds){


            ArrayList<Long> campaignIds = feedsByCampaign.get(feedId);

            SitelinksReport sitelink = new SitelinksReport();
            sitelink.FeedId = feedId;

            sitelink.CampaignIds = campaignIds;

            int offset = 0;
            Selector selector = new Selector();

            selector.setPaging(new Paging(offset, PAGE_SIZE));

            Predicate feedIdPredicate =
                    new Predicate("FeedId", PredicateOperator.IN, new String[]{feedId.toString()});

            selector.setPredicates(new Predicate[]{feedIdPredicate});
            selector.setFields(new String[]{"FeedId", "FeedItemId", "AttributeValues", "Status"});

            FeedItemPage page = null;

            try {
                do {
                    page = feedItemService.get(selector);
                    if (page.getEntries() != null) {
                        for (FeedItem feedItem : page.getEntries()) {
                            GA_FeedItem item = new GA_FeedItem();


                            item.FeedItemId = feedItem.getFeedItemId();

                            item.FeedAttributes = new ArrayList<GA_FeedAttribute>();

                            for (FeedItemAttributeValue attValue : feedItem.getAttributeValues()){

                                GA_FeedAttribute attribute = new GA_FeedAttribute();

                                attribute.FeedAttrId = attValue.getFeedAttributeId();

                                if (attValue.getBooleanValue() != null){
                                    attribute.FeedItemValue = attValue.getBooleanValue().toString();

                                }else if (attValue.getDoubleValue() != null){
                                    attribute.FeedItemValue = attValue.getDoubleValue().toString();
                                }else if (attValue.getStringValue() != null){
                                    attribute.FeedItemValue = attValue.getStringValue().toString();
                                }else if (attValue.getIntegerValue() != null){
                                    attribute.FeedItemValue = attValue.getIntegerValue().toString();
                                }

                                item.FeedAttributes.add(attribute);

                            }
                           // sitelink.Sitelinks.add(item);

                        }



                    }

                    offset += PAGE_SIZE;
                    selector.getPaging().setStartIndex(offset);

                } while (offset < page.getTotalNumEntries());


            } catch (RemoteException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }

            result.add(sitelink);
        }
             */
        } catch (Exception ex) {
            ex.printStackTrace(System.out);
        }


        return result;
    }

    protected ArrayList<LocationExtensionReport> GetFeedItemsLocationExtensionReport(String clientId){

        ArrayList<LocationExtensionReport> result = new ArrayList<LocationExtensionReport>();

        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();
        try {
            FeedItemServiceInterface feedItemService = sf.GetFeedItemServiceInterface(clientId);

            ArrayList<CampaignFeedMapping> feedsByCampaign = GetFeedsByCampaign(clientId, "7");

            LocationExtensionReport sitelink = new LocationExtensionReport();
            sitelink.LocationExtensions = feedsByCampaign;


            result.add(sitelink);
        } catch (Exception ex) {
            ex.printStackTrace(System.out);
        }

        return result;
    }


    protected ArrayList<CallsAdExtensionReport> GetFeedItemsAdExtensionsCallsReport(String clientId){

        ArrayList<CallsAdExtensionReport> result = new ArrayList<CallsAdExtensionReport>();

        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();
        //FeedItemServiceInterface feedItemService = sf.GetFeedItemServiceInterface(clientId);

        //ArrayList<Long> feedIds = GetFeedIds(clientId, "1");

        ArrayList<CampaignFeedMapping> feedsByCampaign = GetFeedsByCampaign(clientId, "2");

        CallsAdExtensionReport calls = new CallsAdExtensionReport();
        calls.Calls = feedsByCampaign;


        result.add(calls);

        return result;
    }

    protected ArrayList<CallsReport> GetFeedItemsCallsReport(String clientId){

        ArrayList<CallsReport> result = new ArrayList<CallsReport>();

        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();
        try {
            FeedItemServiceInterface feedItemService = sf.GetFeedItemServiceInterface(clientId);

            ArrayList<Long> feedIds = GetFeedIds(clientId, "2");


            for (Long feedId : feedIds) {

                CallsReport call = new CallsReport();
                call.FeedId = feedId;

                int offset = 0;
                Selector selector = new Selector();

                selector.setPaging(new Paging(offset, PAGE_SIZE));

                Predicate feedIdPredicate =
                        new Predicate("FeedId", PredicateOperator.IN, new String[]{feedId.toString()});

                selector.setPredicates(new Predicate[]{feedIdPredicate});
                selector.setFields(new String[]{"FeedId", "FeedItemId", "AttributeValues", "Status"});

                FeedItemPage page = null;

                try {
                    do {
                        page = feedItemService.get(selector);
                        if (page.getEntries() != null) {
                            for (FeedItem feedItem : page.getEntries()) {
                                GA_FeedItem item = new GA_FeedItem();


                                item.FeedItemId = feedItem.getFeedItemId();

                                item.FeedAttributes = new ArrayList<GA_FeedAttribute>();

                                for (FeedItemAttributeValue attValue : feedItem.getAttributeValues()) {

                                    GA_FeedAttribute attribute = new GA_FeedAttribute();

                                    attribute.FeedAttrId = attValue.getFeedAttributeId();

                                    if (attValue.getBooleanValue() != null) {
                                        attribute.FeedItemValue = attValue.getBooleanValue().toString();

                                    } else if (attValue.getDoubleValue() != null) {
                                        attribute.FeedItemValue = attValue.getDoubleValue().toString();
                                    } else if (attValue.getStringValue() != null) {
                                        attribute.FeedItemValue = attValue.getStringValue().toString();
                                    } else if (attValue.getIntegerValue() != null) {
                                        attribute.FeedItemValue = attValue.getIntegerValue().toString();
                                    }

                                    item.FeedAttributes.add(attribute);

                                }
                                call.Calls.add(item);

                            }


                        }

                        offset += PAGE_SIZE;
                        selector.getPaging().setStartIndex(offset);

                    } while (offset < page.getTotalNumEntries());


                } catch (RemoteException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }

                result.add(call);
            }
        } catch (Exception ex) {
            ex.printStackTrace(System.out);
        }

        return result;
    }

    private CampaignFeedMapping GetCampaignFeedMapping(ArrayList<CampaignFeedMapping> feedMappings, Long campaignId){
        CampaignFeedMapping result = null;
        for (CampaignFeedMapping cfm : feedMappings){
            if (cfm.CampaignId == campaignId){
                return cfm;
            }
        }
        return result;
    }

    protected ArrayList<CampaignFeedMapping> GetFeedsByCampaign(String clientId, String placeHolderType){

        //ashMap<Long, ArrayList<Long>> campaignFeedsMapping = new HashMap<Long, ArrayList<Long>>();

        ArrayList<CampaignFeedMapping> feedMappings = new ArrayList<CampaignFeedMapping>();

        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();
        try {
            CampaignFeedServiceInterface campaignFeedService = sf.GetCampaignFeedServiceInterface(clientId);

            int offset = 0;

            // Create selector.
            Selector selector = new Selector();
            selector.setFields(new String[]{
                    "CampaignId",
                    "FeedId",
                    "MatchingFunction"
            });

            ArrayList<Long> validIds = GetFeedIds(clientId, placeHolderType);

            selector.setPaging(new Paging(offset, PAGE_SIZE));

            CampaignFeedPage page = null;

            do {
                page = campaignFeedService.get(selector);
                if (page.getEntries() != null && page.getEntries().length > 0) {

                    for (CampaignFeed cf : page.getEntries()) {

                        if (validIds.contains(cf.getFeedId())) {

                            CampaignFeedMapping cfm = new CampaignFeedMapping();

                            Function f = cf.getMatchingFunction();

                            FunctionOperator fOperator = f.getOperator();

                            FunctionArgumentOperand[] lOperands = f.getLhsOperand();
                            FunctionArgumentOperand[] rOperands = f.getRhsOperand();

                            if (fOperator.equals(FunctionOperator.IN) || fOperator.equals(FunctionOperator.EQUALS)) {

                                RequestContextOperand rco = (RequestContextOperand) lOperands[0];

                                if (rco.getContextType().equals(RequestContextOperandContextType.FEED_ITEM_ID)) {

                                    CampaignFeedMapping cfmAux = GetCampaignFeedMapping(feedMappings, cf.getCampaignId());

                                    if (cfmAux != null) {

                                        CampaignFeedItemMapping cfim = new CampaignFeedItemMapping();

                                        cfim.FeedId = cf.getFeedId();

                                        for (FunctionArgumentOperand rOperand : rOperands) {

                                            ConstantOperand co = (ConstantOperand) rOperand;

                                            if (co.getType().equals(ConstantOperandConstantType.LONG)) {

                                                cfim.FeedItemIds.add(co.getLongValue());
                                            }

                                        }

                                        cfmAux.FeedMapping.add(cfim);
                                        cfm = cfmAux;

                                        feedMappings.add(cfm);

                                    } else {

                                        cfmAux = new CampaignFeedMapping();
                                        cfmAux.CampaignId = cf.getCampaignId();

                                        CampaignFeedItemMapping cfim = new CampaignFeedItemMapping();

                                        cfim.FeedId = cf.getFeedId();

                                        for (FunctionArgumentOperand rOperand : rOperands) {

                                            ConstantOperand co = (ConstantOperand) rOperand;

                                            if (co.getType().equals(ConstantOperandConstantType.LONG)) {

                                                cfim.FeedItemIds.add(co.getLongValue());
                                            }

                                        }

                                        cfmAux.FeedMapping.add(cfim);
                                        cfm = cfmAux;
                                        feedMappings.add(cfm);
                                    }
                                }
                            }
                        }
                    }


                }
                offset += PAGE_SIZE;
                selector.getPaging().setStartIndex(offset);
            } while (offset < page.getTotalNumEntries());
        } catch (Exception exc) {
            exc.printStackTrace(System.out);
        }


         return feedMappings;


    }


    private ArrayList<Long> GetFeedIds(String clientId, String placeHolderType) {
        ArrayList<Long> feedIds = new ArrayList<Long>();
        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();
        try {
            FeedItemServiceInterface feedItemService = sf.GetFeedItemServiceInterface(clientId);


            FeedMappingServiceInterface feedMappingService = sf.GetFeedMappingServiceInterface(clientId);
            int offset = 0;
            Selector selector = new Selector();

            selector.setPaging(new Paging(offset, PAGE_SIZE));

            Predicate feedTypePredicate =
                    new Predicate("PlaceholderType", PredicateOperator.IN, new String[]{placeHolderType});

            selector.setPredicates(new Predicate[]{feedTypePredicate});
            selector.setFields(new String[]{"FeedId", "PlaceholderType", "Status"});

            FeedMappingPage page = null;

            try {
                do {
                    page = feedMappingService.get(selector);
                    if (page.getEntries() != null) {
                        for (FeedMapping feedMapping : page.getEntries()) {

                            if (!(feedIds.contains(feedMapping.getFeedId())))
                                feedIds.add(feedMapping.getFeedId());
                        }
                    }

                    offset += PAGE_SIZE;
                    selector.getPaging().setStartIndex(offset);
                } while (offset < page.getTotalNumEntries());
            } catch (RemoteException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
        } catch (Exception ex) {
            ex.printStackTrace(System.out);
        }

        return feedIds;
    }

}
